﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using static IchiaTester.MainForm;


namespace IchiaTester.Utils
{
    /**
     * Adams的工具类
     */
    public class ProcessHandler
    {
        #region DLL_IMPORT
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();


        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

        [DllImport("user32.dll")]
        public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

        [DllImport("user32.dll")]
        private static extern int SetCursorPos(int x, int y);

        #endregion

        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }


        //檢查指定的程式是否已經執行
        public static Process GetProcessByName(string processName)
        {
            Process[] processes = Process.GetProcessesByName(processName);
            return processes.Length > 0 ? processes[0] : null;
        }

        public static RECT? GetWindowPosition(string targetWindowName)
        {
            // 找到目標視窗
            IntPtr targetWindowHandle = FindWindow(null, targetWindowName);
            if (targetWindowHandle == IntPtr.Zero)
            {
                Console.WriteLine($"無法找到視窗");
                return null;
            }

            SetForegroundWindow(targetWindowHandle);

            // 取得目標視窗的位置
            RECT rect;
            if (GetWindowRect(targetWindowHandle, out rect))
            {
                Console.WriteLine($"Window X,Y: {rect.Left},{rect.Top}");
                return rect;
            }
            return null; // 如果無法獲取視窗位置也返回 null
        }

        public static void ControlMouseClick(int x, int y)
        {
            mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
            mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
        }

        public static void SimMouseClick(string targetWindowName , int winPositionX, int winPositionY)
        {
            //取得視窗位置
            GetWindowPosition(targetWindowName);
            //指定位置點擊滑鼠
            ControlMouseClick(winPositionX, winPositionY);
        }

        public static Color GetColorAt(int x, int y)
        {
            // 创建一个位图对象
            using (Bitmap bitmap = new Bitmap(1, 1))
            {
                // 使用 Graphics 对象从屏幕截取一个像素
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(new Point(x, y), Point.Empty, new Size(1, 1));
                }

                // 获取位图中的像素颜色
                return bitmap.GetPixel(0, 0);
            }
        }

    }


    public class GroupBoxPaint
    {

        public void groupbox_Paint(object sender, PaintEventArgs e)
        {
            GroupBox gBox = (GroupBox)sender;
            // 设置绘制颜色
            Pen p = new Pen(Color.LightSkyBlue, 3); // 設定線寬和顏色

            e.Graphics.Clear(gBox.BackColor);
            e.Graphics.DrawString(gBox.Text, gBox.Font, Brushes.Blue, 10, 1);
            var vSize = e.Graphics.MeasureString(gBox.Text, gBox.Font);
            e.Graphics.DrawLine(p, 1, vSize.Height / 2, 8, vSize.Height / 2);
            e.Graphics.DrawLine(p, vSize.Width + 8, vSize.Height / 2, gBox.Width - 2, vSize.Height / 2);
            e.Graphics.DrawLine(p, 1, vSize.Height / 2, 1, gBox.Height - 2);
            e.Graphics.DrawLine(p, 1, gBox.Height - 2, gBox.Width - 2, gBox.Height - 2);
            e.Graphics.DrawLine(p, gBox.Width - 2, vSize.Height / 2, gBox.Width - 2, gBox.Height - 2);
        }
    }

    public class SerialPortHelper
    {
        /*
         尋找可用的COM port
         */
        public static List<string> GetAvailableComPorts()
        {
            List<string> availablePorts = new List<string>();

            // 使用 SerialPort.GetPortNames() 方法獲取可用的 COM Port 名稱
            string[] portNames = SerialPort.GetPortNames();

            // 將可用的 COM Port 名稱添加到列表中
            foreach (string portName in portNames)
            {
                availablePorts.Add(portName);
            }

            return availablePorts;
        }

        public static bool PortIsExist(string targetPort)
        {
            //Get all available serial ports
            string[] ports = SerialPort.GetPortNames();

            //檢查指定serial port是否存在
            bool portExists = Array.Exists(ports, port => port.Equals(targetPort, StringComparison.OrdinalIgnoreCase));

            if (portExists)
            {
                Console.WriteLine($"端口 {targetPort} 存在。");
                return true;
            }
            else
            {
                Console.WriteLine($"端口 {targetPort} 不存在。");
                return false;
            }
        }
    }

    public class XmlHandler
    {
        /// <summary>
        /// 追加节点
        /// </summary>
        /// <param name="filePath">XML文档绝对路径</param>
        /// <param name="xPath">范例: @"Skill/First/SkillItem"</param>
        /// <param name="xmlNode">XmlNode节点</param>
        /// <returns></returns>
        public static bool AppendChild(string filePath, string xPath, XmlNode xmlNode)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(filePath);
                XmlNode xn = doc.SelectSingleNode(xPath);
                XmlNode n = doc.ImportNode(xmlNode, true);
                xn.AppendChild(n);
                doc.Save(filePath);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 从XML文档中读取节点追加到另一个XML文档中
        /// </summary>
        /// <param name="filePath">需要读取的XML文档绝对路径</param>
        /// <param name="xPath">范例: @"Skill/First/SkillItem"</param>
        /// <param name="toFilePath">被追加节点的XML文档绝对路径</param>
        /// <param name="toXPath">范例: @"Skill/First/SkillItem"</param>
        /// <returns></returns>
        public static bool AppendChild(string filePath, string xPath, string toFilePath, string toXPath)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(toFilePath);
                XmlNode xn = doc.SelectSingleNode(toXPath);

                XmlNodeList xnList = ReadNodes(filePath, xPath);
                if (xnList != null)
                {
                    foreach (XmlElement xe in xnList)
                    {
                        XmlNode n = doc.ImportNode(xe, true);
                        xn.AppendChild(n);
                    }
                    doc.Save(toFilePath);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }


        /// <summary>
        /// 读取XML文档
        /// </summary>
        /// <param name="filePath">XML文件绝对路径</param>
        /// <returns></returns>
        public static XmlDocument LoadXmlDoc(string filePath)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(filePath);
                return doc;
            }
            catch
            {
                return null;
            }
        }


        /// <summary>
        /// 读取XML的所有子节点
        /// </summary>
        /// <param name="filePath">XML文件绝对路径</param>
        /// <param name="xPath">范例: @"Skill/First/SkillItem"</param>
        /// <returns></returns>
        public static XmlNodeList ReadNodes(string filePath, string xPath)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(filePath);
                XmlNode xn = doc.SelectSingleNode(xPath);
                XmlNodeList xnList = xn.ChildNodes;  //得到该节点的子节点
                return xnList;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 修改XML指定的節點值
        /// </summary>
        /// 範例:
        /// XmlModifier modifier = new XmlModifier();
        /// modifier.ModifyXmlNode("path/to/your/xmlfile.xml", "/Root/NodeToModify", "NewValue");
        public static void UpdateNodeInnerText(string filePath, string nodeXPath, string newValue)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filePath);

            XmlNode node = xmlDoc.SelectSingleNode(nodeXPath);
            if (node != null)
            {
                node.InnerText = newValue;
                xmlDoc.Save(filePath); // 保存修改后的XML文件
            }
        }

        /// <summary>
        /// 修改XML指定的節點值
        /// </summary>
        /// XmlNodeRemover remover = new XmlNodeRemover();
        /// remover.RemoveNode("path/to/your/xmlfile.xml", "/Root/NodeToRemove");
        public static void RemoveNode(string filePath, string nodeXPath)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filePath);

            XmlNode nodeToRemove = xmlDoc.SelectSingleNode(nodeXPath);
            if (nodeToRemove != null)
            {
                nodeToRemove.ParentNode.RemoveChild(nodeToRemove);
            }

            xmlDoc.Save(filePath); // 保存更改
        }

    }


    public class ListViewCell
    {
        /// <summary>
        /// 单元格所在的行。
        /// </summary>
        public ListViewItem Item { get; set; }
        /// <summary>
        /// Item 的 Index 值会变成 -1，暂时未找到原因，用这个代替。
        /// </summary>
        public int ItemIndex { get; set; }
        /// <summary>
        /// 单元格所在的列。
        /// </summary>
        public ColumnHeader Column { get; set; }
        /// <summary>
        /// 单元格相对于 ListView 的大小和位置。
        /// </summary>
        public Rectangle Bounds { get; set; }
    }
    public class ListViewCellLocator
    {
        [DllImport("user32")]
        public static extern int GetScrollPos(int hwnd, int nBar);


        /// <summary>
        /// 根据位置 x、y 获得 ListViewCell。
        /// </summary>
        /// <param name="listView"></param>
        /// <param name="x">工作区坐标表示的 x 轴坐标。</param>
        /// <param name="y">工作区坐标表示的 y 轴坐标。</param>
        /// <returns></returns>
        public static ListViewCell GetCell(ListView listView, int x, int y)
        {
            ListViewCell cell = new ListViewCell();

            // 获得单元格所在的行。
            cell.Item = listView.GetItemAt(x, y);
            if (cell.Item == null)
            {
                return null;
            }
            cell.ItemIndex = cell.Item.Index; // 现在 Item.Index 还能用

            // 根据各列宽度，获得单元格所在的列，以及 Bounds。
            int currentX = cell.Item.GetBounds(ItemBoundsPortion.Entire).Left; // 依次循环各列，表示各列的起点值
            int scrollLeft = GetScrollPos(listView.Handle.ToInt32(), 0); // 可能出现了横向滚动条，左边隐藏起来的宽度
            for (int i = 0; i < listView.Columns.Count; i++)
            {
                if (scrollLeft + x >= currentX &&
                    scrollLeft + x < currentX + listView.Columns[i].Width)
                {
                    cell.Column = listView.Columns[i]; // 列找到了
                    Rectangle itemBounds = cell.Item.GetBounds(ItemBoundsPortion.Entire);
                    cell.Bounds = new Rectangle(currentX,
                        itemBounds.Y,
                        listView.Columns[i].Width,
                        itemBounds.Height);
                    break;
                }
                currentX += listView.Columns[i].Width;
            }

            if (cell.Column == null)
            {
                return null;
            }
            return cell;
        }
    }
    public class EditableListViewSubmittingEventArgs : EventArgs
    {
        public ListViewCell Cell { get; set; }
        public string Value { get; set; }
    }
    public delegate void EditableListViewSubmitting(object sender, EditableListViewSubmittingEventArgs e);
    public class EditableListView
    {
        public event EditableListViewSubmitting Submitting;

        private ListView ListView { get; set; }
        private Point MousePosition = new Point();
        private TextBox EditBox { get; set; }
        public int[] TextBoxColumns { get; set; }

        public EditableListView(ListView listView)
        {
            // 初始化 EditBox
            EditBox = new TextBox();
            EditBox.Visible = false;
            EditBox.KeyUp += new KeyEventHandler(delegate (object sender, KeyEventArgs e)
            {
                if (e.KeyCode == Keys.Escape)
                {
                    LeaveEdit();
                }
                else if (e.KeyCode == Keys.Enter)
                {
                    if (Submitting != null)
                    {
                        EditableListViewSubmittingEventArgs args = new EditableListViewSubmittingEventArgs();
                        if (EditBox.Tag != null)
                        {
                            args.Cell = (ListViewCell)EditBox.Tag;
                        }
                        else
                        {
                            args.Cell = null;
                        }
                        args.Value = EditBox.Text;
                        Submitting(listView, args);
                    }
                }
            });

            // 设置 ListView
            ListView = listView;
            ListView.MouseMove += new MouseEventHandler(delegate (object sender, MouseEventArgs e)
            {
                // 记录鼠标位置，便于在鼠标动作中使用（有些鼠标动作，比如双击，事件中并不传递鼠标双击时的位置）。
                MousePosition.X = e.X;
                MousePosition.Y = e.Y;
            });

            EditBox.Parent = ListView;

            // 事件
            ListView.DoubleClick += new EventHandler(delegate (object sender, EventArgs e)
            {
                ListViewCell cell = ListViewCellLocator.GetCell(this.ListView, MousePosition.X, MousePosition.Y);

                if (cell == null)
                {
                    return;
                }

                if (TextBoxColumns.Contains(cell.Column.Index))
                {
                    // 设置 EditBox 的位置、大小、内容、可显示等。
                    EditBox.Bounds = cell.Bounds;
                    EditBox.Text = cell.Item.SubItems[cell.Column.Index].Text;
                    EditBox.Visible = true;
                    EditBox.Focus();
                    EditBox.Tag = cell;
                }
            });
        }


        public bool IsEditableColumn(int columnIndex)
        {
            if (TextBoxColumns.Contains(columnIndex))
            {
                return true;
            }

            return false;
        }


        public void LeaveEdit()
        {
            EditBox.Visible = false;
            EditBox.Tag = null;
        }
    }
}
